/*
 * Residue.h
 *
 *  Created on: Feb 11, 2012
 *      Author: marchi
 */

#ifndef RESIDUE_H_
#define RESIDUE_H_
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>

#include <map>
#include <list>
#include <set>
#include <boost/regex.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex.hpp>
#include "Tokens.h"

using namespace std;
using namespace boost;
using TokenNS::Tokens;

static regex re_sep0("\\n");
static regex re_split("[\\t\\n\\r\\s][\\t\\n\\r\\s]*");
static regex re_squares("\\[ *(\\w*) *\\]");
static regex re_atoms("\\[ *(atoms) *\\]");
static regex re_bonds("\\[ *(bonds) *\\]");
static regex re_impropers("\\[ *(impropers) *\\]");
typedef map<string,string> Mapss;
typedef map<string,vector<string> >::iterator MapIter;

class Connected{
	void getVector(vector<string> y, string x, char what='A'){
		vector<string>::iterator itc;
		for(itc=y.begin();itc<y.end();++itc)
			if(*itc->begin() != what)
				if(itc->compare(x) != 0) con.push_back(*itc);
	}
	vector<string> con;
public:
	Connected(){};
	Connected(vector<string> y, string x, char what='A'){getVector(y,x,what);}
	Connected & operator()(vector<string> y, string x, char what='A'){getVector(y,x,what);return *this;}
	string operator[](int i){return con.at(i);};
	~Connected(){con.clear();};
};
class MyHDB{
	int nr;
	int ntype;
	vector<string> series;
public:
	MyHDB():nr(0),ntype(0) {};
	MyHDB(int nnr, int nntype, vector<string>  & ss):nr(nnr),ntype(nntype),series(ss) {};
	~MyHDB(){series.clear();};
	friend std::ofstream & operator<<(std::ofstream & out, MyHDB & y){
		out << right << fixed << y.nr << "\t" << y.ntype ;
		for(unsigned int i=0; i<y.series.size();i++) out << right << fixed << "\t" << y.series[i];
		out << "\n";
		return out;
	}
	friend std::ostream & operator<<(std::ostream & out, MyHDB & y){
		out << right << fixed << y.nr << "\t" << y.ntype ;
		for(unsigned int i=0; i<y.series.size();i++) out << right << fixed << "\t" << y.series[i];
		out << "\n";
		return out;
	}
};
struct MapSort{
	bool operator()(const MapIter & y1,const MapIter & y2){
		stringstream ss;
		const string & l1=y1->second[y1->second.size()-1];
		const string & l2=y2->second[y2->second.size()-1];
		int j1,j2;
		ss << l1 << " "<< l2;
		ss >>j1 >> j2;
		return j1<j2;
	}
};
class Residue {
	map<char,int> error;
	map<string,int> errors;
	string label;
	vector<MyHDB> res;
	map<string,vector<string> > atoms;
	void GetType(string,string,vector<string> &,vector<string> &,vector<string> &, map<string, vector<string> > &);
	void its_error(char);
	void its_error(string);
	static bool force;
	void find_bonds(map<string,string>::iterator);
	void find_atoms(map<string,string>::iterator);
public:
	void error_report();
	Residue();
	Residue(string, string);
	Residue(string, Mapss &);
	virtual ~Residue();
	static void Force(){force=true;};
	friend std::ofstream & operator<<(std::ofstream & out, Residue & y){
		out << left << fixed << setw(4) << y.label << right << setw(5) << y.res.size() << "\n";
		for(unsigned int i=0;i<y.res.size();i++)  out << y.res[i];
		return out;
	}
	friend std::ostream & operator<<(std::ostream & out, Residue & y){
		out << left << fixed << setw(4) << y.label << right << setw(5) << y.res.size() << "\n";
		for(unsigned int i=0;i<y.res.size();i++)  out << y.res[i];
		return out;
	}
};

#endif /* RESIDUE_H_ */
